package com.fone.player.storage.download;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import com.fone.player.entity.Download;
import com.fone.player.storage.FileDownloadDataBaseAdapter;
import com.fone.player.storage.StorageModule;
import com.fone.player.util.L;
import com.fone.player.util.SystemUtil;

/**
 * 
 * app下载任务
 * 
 * @author wangyang
 * @since 2014-8-12
 */
public class DownloadAppRunnable implements Runnable {
	private static final String TAG = DownloadAppRunnable.class.getSimpleName();
	/**
	 * 连接超时60秒
	 */
	private static final int mConnectTimeout = 60 * 1000;
	/**
	 * 读取超时30秒
	 */
	private static final int mReadTimeout = 30 * 1000;

	private Download mDownload = null;

	// 是否停止
	private boolean mIsStop = false;
	private Handler mHandler = null;
	private Timer mTimer = new Timer();

	public void setDownload(Download download) {

		Message msg = new Message();
		Bundle bundle = new Bundle();
		bundle.putParcelable(Download.DOWNLOAD, mDownload);
		msg.setData(bundle);
		msg.what = StorageModule.MSG_DOWNLOAD_PROGRESS;
		mHandler.sendMessage(msg);

		long alreadySize = mDownload.getDownloadAlreadySize();
		long totalSize = mDownload.getDownloadTotalSize();

		mDownload = download;

		// 恢复进度
		mDownload.setDownloadAlreadySize(alreadySize);
		mDownload.setDownloadTotalSize(totalSize);

		FileDownloadDataBaseAdapter.getInstance().updateDownload(mDownload);

	}

	public Download getDownload() {
		return mDownload;
	}

	public boolean isIsStop() {
		return mIsStop;
	}

	public void setIsStop(boolean isStop) {

		mIsStop = isStop;
	}

	public DownloadAppRunnable(Handler handler, Download download) {
		mDownload = download;
		mHandler = handler;
	}

	@Override
	public void run() {
		mIsStop = false;
		L.v(TAG, "run", "start url=" + mDownload.getDownloadUrl());
		String versionName = mDownload.getDownloadVersionNameByUrl(
				mDownload.getDownloadUrl(), mDownload.getDownloadFileName());
		mDownload.setDownloadVersionName(versionName);

		// 判断上次是否有未完成任务
		Download download = FileDownloadDataBaseAdapter.getInstance()
				.getDownload(mDownload.getDownloadUrl());
		if (download == null) {
			StringBuilder filePath = new StringBuilder();
			filePath.append(SystemUtil
					.getFoneCacheFolder(SystemUtil.DOWNLOAD_APK_TYPE));
			filePath.append(File.separator);
			filePath.append(mDownload.getDownloadFileName());
			filePath.append(".apk");
			L.v(TAG, "run", "filePath=" + filePath);
			mDownload.setDownloadStoragePath(filePath.toString());
			mDownload.setDownloadStateType(Download.DOWNLOAD_STATE_WAITING);
			File file = new File(mDownload.getDownloadStoragePath());
			if (file.exists()) {
				file.delete();
			}
			// 如果没有, 则创建一个新记录存入
			FileDownloadDataBaseAdapter.getInstance().addDownload(mDownload);
		} else {

			// 创建目录
			SystemUtil.getFoneCacheFolder(SystemUtil.DOWNLOAD_APK_TYPE);
			if (!mDownload.getDownloadVersionName().equals(
					download.getDownloadVersionName())) {
				// 可以升级
				mDownload.setDownloadIsUpgrade(true);
			} else {
				// 不可以升级
				mDownload.setDownloadIsUpgrade(false);
			}
			mDownload.setDownloadAlreadySize(0);
			mDownload.setDownloadTotalSize(download.getDownloadTotalSize());
			mDownload.setDownloadStateType(download.getDownloadStateType());
			mDownload.setDownloadStoragePath(download.getDownloadStoragePath());
			mDownload.setDownloadIsUpgrade(download.getDownloadIsUpgrade());
		}

		Message msg = new Message();
		Bundle bundle = new Bundle();
		mDownload.setErrorCode(Download.DOWNLOAD_SUCCESS);
		bundle.putParcelable(Download.DOWNLOAD, mDownload);
		msg.setData(bundle);
		msg.what = StorageModule.MSG_DOWNLOAD_PROGRESS;
		mHandler.sendMessage(msg);
		L.v(TAG, "run", "MSG_DOWNLOAD_PROGRESS start notification");

		// 解决首页刷新图片缓慢问题
		if (mDownload.getDownloadIsLimitSpeed()) {

			// 限速100KB/s
			limitSpeedDownloadFile(100);

		} else {

			// 全速下载
			limitSpeedDownloadFile(0);

		}

		mIsStop = true;
	}

	/**
	 * 
	 * 限速下载文件
	 * 
	 * @param speed
	 *            每秒允许下载的字节数
	 * @return void
	 */
	public void limitSpeedDownloadFile(long speed) {
		L.v(TAG, "limitSpeedDownloadFile",
				"start url=" + mDownload.getDownloadUrl());
		Message msg = new Message();
		Bundle bundle = new Bundle();
		RandomAccessFile randomAccessFile = null;
		InputStream inputStream = null;
		long length = 0;
		try {
			URL url = new URL(mDownload.getDownloadUrl());
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			// 设置超时时间
			conn.setConnectTimeout(mConnectTimeout);
			conn.setReadTimeout(mReadTimeout);
			if (conn.getResponseCode() == 200) {
				length = conn.getContentLength();
			}

			File file = new File(mDownload.getDownloadStoragePath());

			if (!file.exists()) {

				L.v(TAG, "limitSpeedDownloadFile", "create new file path="
						+ mDownload.getDownloadStoragePath());

				file.createNewFile();

				// 文件被删除,更新进度为0
				mDownload.setDownloadAlreadySize(0);
				mDownload.setDownloadTotalSize(length);
				FileDownloadDataBaseAdapter.getInstance().updateDownload(
						mDownload);

			} else {
				switch (mDownload.getDownloadStateType()) {
				case Download.DOWNLOAD_STATE_FINISH:
					L.v(TAG, "fullSpeedDownloadFile",
							"isUpgrade=" + mDownload.getDownloadIsUpgrade());
					if (mDownload.getDownloadIsUpgrade()) {
						// 需要升级,重新下载
						L.v(TAG, "limitSpeedDownloadFile",
								"delete already exists file,and already upgrade");
						file.delete();
						file.createNewFile();
						FileDownloadDataBaseAdapter.getInstance()
								.updateDownloadIsUpgrade(
										mDownload.getDownloadUrl(), false);
					} else {
						L.v(TAG, "limitSpeedDownloadFile",
								"file already exists,unupgrade");
						mDownload.setDownloadAlreadySize(mDownload
								.getDownloadTotalSize());
						mDownload.setDownloadTotalSize(length);
						mDownload.setErrorCode(Download.DOWNLOAD_SUCCESS);
						mDownload
								.setDownloadStateType(Download.DOWNLOAD_STATE_FINISH);
						msg = new Message();
						bundle = new Bundle();
						bundle.putParcelable(Download.DOWNLOAD, mDownload);
						msg.setData(bundle);
						msg.what = StorageModule.MSG_DOWNLOAD_SUCCESS;
						mHandler.sendMessage(msg);
						return;
					}
					break;
				default:
					L.v(TAG,
							"limitSpeedDownloadFile",
							"unsuccess,downloadState="
									+ mDownload.getDownloadStateType());
					// 未下载完成,删除临时文件
					file.delete();
					file.createNewFile();
					FileDownloadDataBaseAdapter.getInstance()
							.updateDownloadIsUpgrade(
									mDownload.getDownloadUrl(), false);
					break;
				}

			}
			// 文件被删除,更新进度为0
			mDownload.setDownloadAlreadySize(0);
			mDownload.setDownloadTotalSize(length);
			FileDownloadDataBaseAdapter.getInstance().updateDownload(mDownload);

			url = new URL(mDownload.getDownloadUrl());
			// long start = download.getDownloadAlreadySize(); // 开始位置 += 已下载量
			// long end = (id + 1) * partLen - 1;
			HttpURLConnection httpURLConnection = (HttpURLConnection) url
					.openConnection();
			httpURLConnection.setConnectTimeout(mConnectTimeout);
			httpURLConnection.setReadTimeout(mReadTimeout);

			// 开始位置
			long start = length == file.length() ? 0 : file.length();
			// 获取指定位置的数据，Range范围如果超出服务器上数据范围, 会以服务器数据末尾为准
			httpURLConnection.setRequestProperty("Range", "bytes=" + start
					+ "-" + length);
			randomAccessFile = new RandomAccessFile(file, "rws");

			randomAccessFile.seek(start);

			// 开始读写数据
			inputStream = httpURLConnection.getInputStream();
			int pack = 10240; // 10K bytes
			speed = speed * 1024;// 将速度换算成字节
			// int sleep = 200; //每秒5次 即5*10K bytes每秒
			int sleep = 0;
			if (speed != 0) {
				sleep = (int) Math.floor(1000 * pack / speed) + 1;
				L.v(TAG, "downloadFile", "speed=" + speed + " sleep=" + sleep
						+ " url=" + mDownload.getDownloadUrl());
			}
			int maxCount = (int) Math.floor((length - start) / pack) + 1;
			L.v(TAG, "downloadFile", "maxCount=" + maxCount + " url="
					+ mDownload.getDownloadUrl());
			int oldPrecent = 0;
			byte[] buf = new byte[1024 * 10];
			int len;

			while ((len = inputStream.read(buf)) != -1) {

				if (file.canWrite()) {
					randomAccessFile.write(buf, 0, len);
				} else {

					L.e(TAG,
							"run",
							"DOWNLOAD_IO_EXCEPTION"
									+ mDownload.getDownloadFileName()
									+ "升级包下载失败,本地路径不能写数据");
					// 不能写数据,io异常(usb存储模式)
					throw new IOException();
				}

				long currentLength = mDownload.getDownloadAlreadySize() + len;
				if (currentLength > mDownload.getDownloadTotalSize()) {
					currentLength = 0;
				}
				mDownload.setDownloadAlreadySize(currentLength);
				mDownload.setErrorCode(Download.DOWNLOAD_SUCCESS);
				mDownload
						.setDownloadStateType(Download.DOWNLOAD_STATE_DOWNLOADING);
				// 防止刷新频率过高,页面卡死
				if (mDownload.getDownloadPercentNum() == 0
						|| mDownload.getDownloadPercentNum() - oldPrecent >= 5) {
					oldPrecent = mDownload.getDownloadPercentNum();
					msg = new Message();
					bundle = new Bundle();
					bundle.putParcelable(Download.DOWNLOAD, mDownload);
					msg.setData(bundle);
					msg.what = StorageModule.MSG_DOWNLOAD_PROGRESS;
					mHandler.sendMessage(msg);
				}

				if (sleep != 0) {
					try {

						Thread.sleep(sleep);
						// L.v(TAG, "downloadFile", "sleep=" + sleep +
						// " url="
						// + mDownload.getDownloadUrl());

					} catch (InterruptedException e) {
					}
				}
			}
			L.v(TAG, "downloadFile", "DOWNLOAD_STATE_FINISH");
			mDownload.setDownloadAlreadySize(mDownload.getDownloadTotalSize());
			mDownload.setDownloadTotalSize(length);
			mDownload.setErrorCode(Download.DOWNLOAD_SUCCESS);
			mDownload.setDownloadStateType(Download.DOWNLOAD_STATE_FINISH);
			msg = new Message();
			bundle = new Bundle();
			bundle.putParcelable(Download.DOWNLOAD, mDownload);
			msg.setData(bundle);
			msg.what = StorageModule.MSG_DOWNLOAD_SUCCESS;
			mHandler.sendMessage(msg);
			// 更新数据库
			FileDownloadDataBaseAdapter.getInstance().updateDownload(mDownload);
		} catch (MalformedURLException e) {
			if (e != null) {
				e.printStackTrace();
			}
			mDownload.setDownloadErrorMessage(mDownload.getDownloadFileName()
					+ "下载失败");
			L.e(TAG, "run",
					"MalformedURLException " + mDownload.getDownloadFileName()
							+ "升级包下载失败,连接格式或路径错误");
			mDownload.setErrorCode(Download.DOWNLOAD_MALFORMED_URL_EXCEPTION);
			mDownload.setDownloadStateType(Download.DOWNLOAD_STATE_ERROR);
			msg = new Message();
			bundle = new Bundle();
			bundle.putParcelable(Download.DOWNLOAD, mDownload);
			msg.setData(bundle);
			msg.what = StorageModule.MSG_DOWNLOAD_ERROR;
			mHandler.sendMessage(msg);
			FileDownloadDataBaseAdapter.getInstance().deleteDownload(
					mDownload.getDownloadUrl());
		} catch (IOException e) {
			if (e != null) {
				e.printStackTrace();
			}
			if (e instanceof FileNotFoundException) {
				mDownload.setDownloadErrorMessage(mDownload
						.getDownloadFileName() + "下载失败");
				L.e(TAG,
						"run",
						"FileNotFoundException "
								+ mDownload.getDownloadFileName()
								+ "升级包下载失败,连接地址失效");
			} else {
				mDownload.setDownloadErrorMessage(mDownload
						.getDownloadFileName() + "下载失败");
				L.e(TAG,
						"run",
						"DOWNLOAD_IO_EXCEPTION"
								+ mDownload.getDownloadFileName() + "升级包下载失败");
			}
			mDownload.setErrorCode(Download.DOWNLOAD_IO_EXCEPTION);
			mDownload.setDownloadStateType(Download.DOWNLOAD_STATE_ERROR);
			msg = new Message();
			bundle = new Bundle();
			bundle.putParcelable(Download.DOWNLOAD, mDownload);
			msg.setData(bundle);
			msg.what = StorageModule.MSG_DOWNLOAD_ERROR;
			mHandler.sendMessage(msg);
			FileDownloadDataBaseAdapter.getInstance().deleteDownload(
					mDownload.getDownloadUrl());
		} finally {

			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					if (e != null) {
						e.printStackTrace();
					}

				}
			}
			if (randomAccessFile != null) {
				try {
					randomAccessFile.close();
				} catch (IOException e) {
					if (e != null) {
						e.printStackTrace();
					}

				}
			}

		}
	}

	public void startSendMessage() {
		if (mTimer != null) {
			mTimer.schedule(new TimerTask() {

				@Override
				public void run() {
					Message msg = new Message();
					Bundle bundle = new Bundle();
					bundle.putParcelable(Download.DOWNLOAD, mDownload);
					msg.setData(bundle);
					msg.what = StorageModule.MSG_DOWNLOAD_PROGRESS;
					mHandler.sendMessage(msg);
				}
			}, 2000);
		}

	}

	public void stopSendMessage() {
		if (mTimer != null) {
			mTimer.purge();
			mTimer.cancel();
		}
	}
}